package logger

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

// 基于 zap 封装
var lg *WZGLogger

type WZGLogger struct {
	zapLogger *zap.Logger
	zapSuger  *zap.SugaredLogger
	off       bool

	level zap.AtomicLevel
	conf  *LoggerConfig

	fileWriter *lumberjack.Logger
	mqWriter   IAdapterWriter
}

type LoggerConfig struct {
	Level       string         `yaml:"level"`
	ConsoleOnly bool           `yaml:"console_only"`
	Encoding    string         `yaml:"encoding"`
	Writers     *LoggerWriters `yaml:"writers"`
}

type LoggerWriters struct {
	FileConf map[string]interface{} `yaml:"file"`
}

func InitLogger(cfg *LoggerConfig, options ...zap.Option) error {
	if cfg == nil {
		stdZapLogger(options...)
		return nil
	}

	if cfg.ConsoleOnly {
		stdZapLogger()
		return nil
	}

	myZapLogger(cfg, options...)
	defer lg.zapLogger.Sync()

	return nil
}

func stdZapLogger(options ...zap.Option) {
	conf := zap.NewDevelopmentConfig()
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		MessageKey:     "message",
		StacktraceKey:  "stacktrace",
		EncodeLevel:    zapcore.CapitalColorLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
	conf.EncoderConfig = encoderConfig
	zapLogger, _ := conf.Build(options...)

	lg = &WZGLogger{zapLogger: zapLogger, zapSuger: zapLogger.Sugar(), level: conf.Level}
}

func toZapLevel(level string) zapcore.Level {
	var zapLevel zapcore.Level
	switch level {
	case "info":
		zapLevel = zap.InfoLevel
	case "warn":
		zapLevel = zap.WarnLevel
	case "error":
		zapLevel = zap.ErrorLevel
	default:
		zapLevel = zap.DebugLevel
	}
	return zapLevel
}

func GetLogger() *WZGLogger {
	return lg
}

func SetLoggerEnable(enable bool) {
	lg.SetLoggerEnable(enable)
}

func SetLoggerLevel(level string) {
	lg.SetLoggerLevel(level)
}

func (l *WZGLogger) SetLoggerEnable(enable bool) {
	l.off = !enable
}

func (l *WZGLogger) SetLoggerLevel(level string) {
	l.level.SetLevel(toZapLevel(level))
}

func (l *WZGLogger) Debug(v ...interface{}) {
	if !l.off {
		lg.zapSuger.Debug(v...)
	}
}

func (l *WZGLogger) Debugf(format string, v ...interface{}) {
	if !l.off {
		lg.zapSuger.Debugf(format, v...)
	}
}

func (l *WZGLogger) Info(v ...interface{}) {
	if !l.off {
		lg.zapSuger.Info(v...)
	}
}

func (l *WZGLogger) Infof(format string, v ...interface{}) {
	if !l.off {
		lg.zapSuger.Infof(format, v...)
	}
}

func (l *WZGLogger) Warn(v ...interface{}) {
	if !l.off {
		lg.zapSuger.Warn(v...)
	}
}

func (l *WZGLogger) Warnf(format string, v ...interface{}) {
	if !l.off {
		lg.zapSuger.Warnf(format, v...)
	}
}

func (l *WZGLogger) Error(v ...interface{}) {
	if !l.off {
		lg.zapSuger.Error(v...)
	}
}

func (l *WZGLogger) Errorf(format string, v ...interface{}) {
	if !l.off {
		lg.zapSuger.Errorf(format, v...)
	}
}

func (l *WZGLogger) Fatal(v ...interface{}) {
	if !l.off {
		lg.zapSuger.Fatal(v...)
	}
}

func (l *WZGLogger) Fatalf(format string, v ...interface{}) {
	if !l.off {
		lg.zapSuger.Fatalf(format, v...)
	}
}

func (l *WZGLogger) Panic(v ...interface{}) {
	if !l.off {
		lg.zapSuger.Panic(v...)
	}
}

func (l *WZGLogger) Panicf(format string, v ...interface{}) {
	if !l.off {
		lg.zapSuger.Panicf(format, v...)
	}
}
